#include "sockethandler.h"
#include "clientmanager.h"
#include "client.h"
#ifndef WIN32
#include <poll.h>
#endif

SocketHandler::SocketHandler(QObject *parent) : QObject(parent)
{
    m_console.addStatusMessage("Create SocketHandler...");


    m_console.addStatusMessage("Create Serversocket...");
    m_serverSocket = new QTcpServer(this);
    m_console.addStatusMessage("Serversocket successfully created!");

    connect(m_serverSocket, SIGNAL(newConnection()), this, SLOT(sendWelcome()));


    m_console.addStatusMessage("Create ClientManager...");
    m_clientManager = new ClientManager(this);

    if( !m_clientManager )
        m_console.addErrorMessage("Cannot create ClientManager!");
    else
        m_console.addStatusMessage("ClientManager successfully created!");


    m_console.addStatusMessage("SocketHandler successfully created!");
}

SocketHandler::~SocketHandler()
{
    delete m_clientManager;
    delete m_serverSocket;
}

void SocketHandler::run()
{
    //bool quit = false;

    m_console.addStatusMessage("Binding Tunnel Server on port %d .", SERVERSOCKET_STANDART_PORT);

    if( !m_serverSocket->listen(QHostAddress::Any, quint16(SERVERSOCKET_STANDART_PORT)) )
    {
        m_console.addErrorMessage("Unsuccessfully bounded on port %d !", SERVERSOCKET_STANDART_PORT);
        m_serverSocket->close();

        return;
    }

    m_console.addStatusMessage("Now listining on port %d", SERVERSOCKET_STANDART_PORT);

    // Have to put this code in a thread...
/*
#ifndef WIN32
    // Check for commands being input from stdin
    string command;
#ifndef WIN32
    pollfd cinfd[1];
    // Theoretically this should always be 0, but one fileno call isn't going to hurt, and if
    // we try to run somewhere that stdin isn't fd 0 then it will still just work
    cinfd[0].fd = fileno(stdin);
    cinfd[0].events = POLLIN;
#else
    HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
#endif
    while(!quit && m_serverSocket->isListening())
    {
#ifndef WIN32
        if (poll(cinfd, 1, 0))
#else
        // This is problematic because input on Windows is not line-buffered so this will return
        // even if getline may block.  I haven't found a good way to fix it, so for the moment
        // I just strongly suggest only running the server from the Python frontend, which does
        // line buffer input.  This does work okay as long as the user doesn't enter characters
        // without pressing enter, and then try to end the server another way (say a remote
        // console command), in which case we'll still be waiting for the stdin EOL and hang.
        if (WaitForSingleObject(h, 0) == WAIT_OBJECT_0)
#endif
        {
            getline(cin, command);

            if(command == "quit")
            {
                quit = true;
                m_console->addWarningMessage("Server is terminating...");
                exit(0);
            }
        }
    }
#endif*/
}

void SocketHandler::sendWelcome()
{
    Package package;
    setupSystemPackage(&package, TUNNEL_COMMANDCATEGORY_COMM, TUNNEL_COMMAND_AUTH);

    // Create new client...
    Client *client = m_clientManager->newClient(m_serverSocket->nextPendingConnection(), connecting);
    connect( client, SIGNAL(signal_newMessage(const QString&, const QString&)), this, SLOT(sendMessageToAll(const QString&, const QString&)) );

    // AuthRequest senden
    client->sendPackage(&package);
}

void SocketHandler::sendMessageToAll(const QString &from, const QString &message)
{
    Package package;
    setupMessagePackage(&package, from, message);

    Client *client = m_clientManager->getFirstClient();

    while( client )
    {
        client->sendPackage(&package);
        client = client->getNextClient();
    }
}
